package com.bonana.core.services.impl;

import com.alibaba.fastjson.JSON;
import com.bonana.core.dao.CustomMapper;
import com.bonana.core.dao.index.IndexBoMapper;
import com.bonana.core.dao.user.*;
import com.bonana.core.entity.CoreUser;
import com.bonana.core.entity.CoreUserProfile;
import com.bonana.core.entity.UserBaseProfile;
import com.bonana.core.entity.mybatis.*;
import com.bonana.core.form.BoPlanFrom;
import com.bonana.core.form.User;
import com.bonana.core.form.UserForm;
import com.bonana.core.form.UserSingleFieldFrom;
import com.bonana.core.result.Response;
import com.bonana.core.result.ResponseCode;
import com.bonana.core.services.BoBoService;
import com.bonana.core.utils.FileInfo;
import com.bonana.core.utils.OssUtils;
import com.bonana.core.utils.SmsUtil;
import com.bonana.core.vo.*;
import com.bonana.utils.*;
import com.github.pagehelper.PageHelper;
import com.google.common.base.CaseFormat;
import com.google.common.base.Splitter;
import com.google.common.net.InetAddresses;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.InvocationTargetException;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/6/27.
 */
@Service
public class BoBoServiceImpl implements BoBoService {
    private Logger logger = LogManager.getLogger(BoBoServiceImpl.class);

    @Autowired
    CoreUserDAO boboDao;
    @Autowired
    CoreUserProfileDAO boboProfileDao;
    @Autowired
    CustomMapper customMapper;
    @Autowired
    IndexBoMapper indexBoMapper;
    @Autowired
    BoFavLogMapper boFavLogMapper;
    @Autowired
    BoboplanMapper boboplanMapper;
    @Autowired
    BoCommentMapper commentMapper;
    @Autowired
    CoreUserFollowerMapper followerMapper;

    @Override
    public int AddBobo(CoreUser user) {
        return boboDao.register(user);
    }

    @Override
    public int DelBoboById(int userId) {
        indexBoMapper.deleteByPrimaryKey(userId);
        boboProfileDao.DelBoboProfile(userId);
        return boboDao.DelBobo(userId);
    }

    public int randPassword() {
        int max = 100000;
        int min = 999999;
        double d = Math.random();
        return (int) (d * (max - min) + min);
    }

    @Override
    public int updateDynamicPwd(String username) {
        String dynamicPassword = String.valueOf(randPassword());
        logger.debug("username:" + username + "   password:" + dynamicPassword);

        if (boboDao.isExists(username)>0) {
            boboDao.updatePassword(username, encodePassword(username, dynamicPassword));
        } else {
            CoreUser coreUser = new CoreUser();
            coreUser.setUsername(username);
            coreUser.setPassword(encodePassword(coreUser.getUsername(), dynamicPassword));
            coreUser.setCreatedTime(TimestampUtil.now());
            coreUser.setUpdatedTime(TimestampUtil.now());
            coreUser.setLastLoginTime(TimestampUtil.now());
            coreUser.setIsRobot((byte) 0);
            coreUser.setStatus((byte) 0);
            coreUser.setCredits(0);
            coreUser.setLevelCredits(0);
            coreUser.setLastLoginIp(0);
            boboDao.register(coreUser);
        }
        SmsUtil.send(username, String.format(SystemConfig.getString("sms.template.dynamicPwd"), dynamicPassword));
        return 1;
    }

    @Override
    public int resetPwd(String username, String pwd, String dpwd) {
        CoreUser co = boboDao.queryUserByUsernameAndPassword(username, encodePassword(username, dpwd));
        if (co==null) {
            return 0;
        }
        boboDao.updatePassword(username, encodePassword(username, pwd));
        if (boboProfileDao.isExists(co.getUid())==0) {
            CoreUserProfile coreUserProfile = new CoreUserProfile();
            coreUserProfile.setUsername(username);
            coreUserProfile.setNickname(username);
            coreUserProfile.setUid(co.getUid());
            coreUserProfile.setCreatedTime(TimestampUtil.now());
            coreUserProfile.setHometownId(38522);
            coreUserProfile.setBwn("86-60-87");
            coreUserProfile.setHeight((float) 160.0);
            coreUserProfile.setWeight((float) 50.0);
            coreUserProfile.setConstellation("水瓶座");
            coreUserProfile.setAvatar("http://oss-cn-shenzhen.aliyuncs.com/gegejie/20160814/5fc2057ee0f648b685f3e8e050bf12ed.jpg");
            boboProfileDao.save(coreUserProfile);
        }
        return co.getUid();
    }

    @Override
    public CoreUser getBoboById(int boboId) {
        return boboDao.queryUserByUid(boboId);
    }

    @Override
    public List<CoreUserProfile> getBobos(int pgNum, int pgSize, String sortType, String query, Integer owner, Integer platformId) {

        String order="";
        if (sortType == null) {
            order = "core_user_profile.updated_time";
        }else if (sortType.equals("hot")) {
            order = "core_user_profile.follower_cnt";
        } else if (sortType.equals("rec")) {
            order = "5*core_user_profile.like_cnt+5*core_user_profile.follower_cnt+core_user_profile.following_cnt";
        }
        PageHelper.startPage(pgNum, pgSize);
        List<CoreUserProfile> list = boboProfileDao.getBobos(order, query, owner, platformId);
        return list;
    }

    @Override
    public List<CoreUserProfile> getHotBobos(int cnt) {
        return customMapper.getHotBobos(cnt);
    }

    @Override
    public List<CoreUserProfile> getNewestBobos(int cnt) {
        return customMapper.getNewestBobos(cnt);
    }

    @Override
    public List<CoreUserProfile> getIndexBobos(int cnt) {
        return customMapper.getIndexBoers(9);
    }

    @Override
    public List<CoreUserProfile> queryAllBoUser() {
        return boboProfileDao.queryAllRobotUser();
    }

    @Override
    public int RemoveFromIndex(int userId) {
        return indexBoMapper.deleteByPrimaryKey(userId);
    }

    @Override
    public int AddToIndex(IndexBo ubo) {
        ubo.setAddTime(new java.util.Date());
        return indexBoMapper.insert(ubo);
    }

    private String encodePassword(String username, String password) {
        return DigestUtils.md5Hex(username + password);
    }

    private void copyToUser(CoreUser coreUser, User user) {
        Assert.notNull(coreUser);
        user.setUid(coreUser.getUid());
        user.setStatus(coreUser.getStatus());
        user.setUsername(coreUser.getUsername());
        user.setCredits(coreUser.getCredits());
        user.setLevelCredits(coreUser.getLevelCredits());
        user.setOpenid(coreUser.getOpenid());
    }

    public UserLoginVO login(String username, String password,  String requestRemoteAddr) {
        UserLoginVO userLoginVO = new UserLoginVO();
        userLoginVO.setResult(new Response(ResponseCode.SUCC));

        if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
            userLoginVO.setResult(new Response(ResponseCode.MISSING_PARAMETER.setArgs(new Object[]{"username", "String"})));
            return userLoginVO;
        }

        CoreUser coreUser = new CoreUser();
        if (boboDao.isExists(username) == 1) {
            if (password.equals("1")) {
                coreUser = boboDao.queryUserByUsername(username);
            } else {
                coreUser = boboDao.queryUserByUsernameAndPassword(username, encodePassword(username, password));
            }
            if (coreUser == null || coreUser.getUid() == 0) {
                userLoginVO.setResult(new Response(ResponseCode.PASSWORD_INCORRECT));
            } else {
                userLoginVO.setResult(new Response(ResponseCode.SUCC));

                boboDao.updateLastLogin(username, InetAddresses.coerceToInteger(InetAddresses.forString(requestRemoteAddr)), TimestampUtil.now());
            }
        }
        if (coreUser != null && coreUser.getUid() > 0) {
            User user = new User();
            copyToUser(coreUser, user);
            userLoginVO.setUser(user);
        } else {
            userLoginVO.setResult(new Response(ResponseCode.USER_NOT_FOUND));
        }
        return userLoginVO;
    }

    @Override
    public AvatarVo updateUserAvatar(int uid, MultipartFile avatarFile) {
        AvatarVo avatarVo = new AvatarVo();
        avatarVo.setResult(new Response(ResponseCode.SUCC));
        if (avatarFile != null) {
            FileInfo fileInfo = OssUtils.putFile(avatarFile);
            String avatarFileUrl = fileInfo.getUrl();
            if (StringUtils.hasText(avatarFileUrl)) {
                avatarVo.setAvatar(avatarFileUrl);
                boboProfileDao.updateUserAvatar(uid, avatarFileUrl);
            } else {
                avatarVo.setResult(new Response(ResponseCode.ERROR));
            }
        } else {
            avatarVo.setResult(new Response(ResponseCode.MISSING_PARAMETER.setArgs(new Object[]{"avatarFile", "File"})));
        }
        return avatarVo;
    }

    public UserProfileVO saveUserProfile(UserForm userForm) {
        UserProfileVO userProfileVO = new UserProfileVO();
        if(userForm == null) {
            logger.error("user from is null");
            userProfileVO.setResult(new Response(ResponseCode.MISSING_PARAMETER.setArgs(new Object[]{"user", "UserForm"})));
            return userProfileVO;
        }
        logger.debug("==============> {}" , JSON.toJSON(userForm));

        if (userForm.getUid() == 0) {
            userProfileVO.setResult(new Response(ResponseCode.MISSING_PARAMETER.setArgs(new Object[]{"uid", "int"})));
            return userProfileVO;
        }

        CoreUserProfile coreUserProfile = new CoreUserProfile();

        MultipartFile avatarFile = userForm.getAvatarFile();

        if (avatarFile != null) {
            FileInfo fileInfo = OssUtils.putFile(avatarFile);
            if (fileInfo != null && StringUtils.hasText(fileInfo.getUrl())) {
                userForm.setAvatar(fileInfo.getUrl());
            }
        }

        try {
            String birthday = userForm.getBirthday();
            if(StringUtils.hasText(birthday)) {
                userForm.setBirthday(null);
            }

            if(userForm.getRegionId() > 0 && userForm.getHometownId() == 0) {
                userForm.setHometownId(userForm.getRegionId());
            }

            PropertyUtils.copyProperties(coreUserProfile, userForm);


            if(StringUtils.hasText(birthday)) {
                coreUserProfile.setBirthday(new Date(DateTool.stringToTimestamp(birthday , "yyyy-MM-dd").getTime()));
            }

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        coreUserProfile.setUpdatedTime(TimestampUtil.now());
        int isSuccess;
        if (boboProfileDao.isExists(coreUserProfile.getUid())==1) {
            isSuccess = boboProfileDao.updateUserProfile(coreUserProfile);
        } else {
            coreUserProfile.setCreatedTime(TimestampUtil.now());
            if(coreUserProfile.getAvatar()==null) {
                coreUserProfile.setAvatar("http://oss-cn-shenzhen.aliyuncs.com/gegejie/20160814/5fc2057ee0f648b685f3e8e050bf12ed.jpg");
            }
            coreUserProfile.setHometownId(38522);
            coreUserProfile.setBwn("86-60-87");
            coreUserProfile.setHeight((float) 160.0);
            coreUserProfile.setWeight((float) 50.0);
            coreUserProfile.setConstellation("水瓶座");
            isSuccess = boboProfileDao.save(coreUserProfile);
//            if (isSuccess) {
//                coreUserDAO.updateStatus(coreUserProfile.getUid(), 1);
//            }
        }
        if (isSuccess>0) {
            boboDao.updateStatus(coreUserProfile.getUid(), 1);
            userProfileVO.setUserProfile(coreUserProfile);
        }
        userProfileVO.setResult(isSuccess==1 ? new Response(ResponseCode.SUCC) : new Response(ResponseCode.ERROR));
        return userProfileVO;
    }

    public int updateSingleField(int uid, UserSingleFieldFrom fieldFrom) {
        String field = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fieldFrom.getField());
        return boboProfileDao.updateSingleField(uid, field, fieldFrom.getVal());
    }



    @Override
    public UserProfileVO saveUser(UserForm userForm, String remoteAddress) {
        if(userForm.getUid() == 0) {
            UserLoginVO userLoginVO = login(userForm.getUsername(), userForm.getPassword(), remoteAddress);
            if(userLoginVO != null) {
                userForm.setUid(userLoginVO.getUser().getUid());
            }
        }
        return saveUserProfile(userForm);
    }



    public UserCardVO queryUserCardByUid(int uid, int fromUid, Long ts) {
        UserCardVO userCardVO = new UserCardVO();
        Timestamp qts = null;
        if (ts > 0) {
            qts = TimestampUtil.toTimestamp(ts);
        }
        CoreUserProfile coreUserProfile = boboProfileDao.queryProfileByUid(uid, qts);
        if (coreUserProfile != null && coreUserProfile.getUid() > 0) {
            userCardVO.setUserProfile(coreUserProfile);
            userCardVO.setTs(coreUserProfile.getUpdatedTime());
        } else {
            userCardVO.setTs(TimestampUtil.toTimestamp(ts));
        }
        //userCardVO.setFollowerCount(coreUserFollowerDAO.countByUid(uid));
        //userCardVO.setFollowingCount(coreUserFollowingDAO.countByUid(uid));
        //userCardVO.setIsFollowing((byte) (coreUserFollowingDAO.isFollowing(fromUid, uid) ? 1 : 0));
        return userCardVO;
    }

    public CoreUserProfile queryUserProfileByUid(int uid, Long ts) {
        Timestamp qts = null;
        if (ts > 0) {
            qts = TimestampUtil.toTimestamp(ts);
        }
        CoreUserProfile coreUserProfile = boboProfileDao.queryProfileByUid(uid, qts);
        return coreUserProfile;
    }

    public UserBaseProfileListVO getUserProfileByUids(String uids) {
        Iterable<String> iterable = Splitter.on(',')
                .trimResults()
                .omitEmptyStrings()
                .split(uids);
        List<Integer> uidList = new ArrayList();
        for (String str : iterable) {
            uidList.add(ConvertUtils.toInteger(str));
        }

        UserBaseProfileListVO profileListVO = new UserBaseProfileListVO();
        List<CoreUserProfile> coreUserProfiles = boboProfileDao.queryUserProfileByUids(uidList);
        List<UserBaseProfile> baseProfiles = new ArrayList<UserBaseProfile>();
        if (coreUserProfiles != null && coreUserProfiles.size() > 0) {
            for (CoreUserProfile coreUserProfile : coreUserProfiles) {
                UserBaseProfile baseProfile = new UserBaseProfile();
                try {
                    PropertyUtils.copyProperties(baseProfile, coreUserProfile);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
                baseProfiles.add(baseProfile);
            }
        }

        profileListVO.setProfiles(baseProfiles);
        return profileListVO;
    }


    public int addFavor(int fromUid, int boid) {
        BoFavLog key = new BoFavLog();
        key.setBoId(boid);
        key.setFromUid(fromUid);
        key.setUpdateTime(new java.util.Date());
        try {
            if (1 == boFavLogMapper.insert(key)) {
                boboProfileDao.updateFavour(boid, 1);
                return 1;
            }
        } catch (Exception e) {

        }
        return 0;
    }

    public int unFavor(int fromUid, int boid) {
        BoFavLogKey key = new BoFavLogKey();
        key.setBoId(boid);
        key.setFromUid(fromUid);
        try {
            int ret = boFavLogMapper.deleteByPrimaryKey(key);
            if (ret == 1) {
                boboProfileDao.updateFavour(boid, -1);
                return 1;
            }
        } catch (Exception e) {
        }
        return 0;
    }

    @Override
    public int addFollow(int fromUid, int boid) {
        CoreUserFollower key = new CoreUserFollower();
        key.setUid(boid);
        key.setFollowerUid(fromUid);
        key.setUpdatedTime(new java.util.Date());
        try {
            if (1 == followerMapper.insert(key)) {
                boboProfileDao.updateFollowerCnt(boid, 1);
                boboProfileDao.updateFollowingCnt(fromUid,1);
                return 1;
            }
        } catch (Exception e) {

        }
        return 0;
    }

    @Override
    public int unFollow(int fromUid, int boid) {
        CoreUserFollower key = new CoreUserFollower();
        key.setUid(boid);
        key.setFollowerUid(fromUid);
        try {
            int ret = followerMapper.deleteByPrimaryKey(key);
            if (ret == 1) {
                boboProfileDao.updateFollowerCnt(boid, -1);
                boboProfileDao.updateFollowingCnt(fromUid, -1);
                return 1;
            }
        } catch (Exception e) {
        }
        return 0;
    }

    @Override
    public List<Boboplan> getBoboPlan(int uid) {
        BoboplanExample ex = new BoboplanExample();
        ex.createCriteria().andUserIdEqualTo(uid);
        ex.setOrderByClause("begin_time asc");
        return boboplanMapper.selectByExample(ex);
    }

    @Override
    public List<BoPlanVo> getBoboPlanDisplay(int uid) {
        return customMapper.getBoPlans(uid);
    }

    @Override
    public Boboplan SaveBoboPlan(BoPlanFrom form) {
        Boboplan plan = form.toPlanModel();
        if (form.getPlanId() == 0) {
            boboplanMapper.insert(plan);
        } else {
            boboplanMapper.updateByPrimaryKeySelective(plan);
        }
        return plan;
    }

    @Override
    public int RemovePlan(int planId) {
        return boboplanMapper.deleteByPrimaryKey(planId);
    }

    @Override
    public Boboplan getBoPlanById(int boplanId) {
        return boboplanMapper.selectByPrimaryKey(boplanId);
    }

    @Override
    public int addComment(int boid, int uid, int parrendId, String content) {
        BoComment bc = new BoComment();
        bc.setBoId(boid);
        bc.setContent(content);
        bc.setCreatedTime(new java.util.Date());
        bc.setParentId(parrendId);
        bc.setUid(uid);
        bc.setIsDeleted(false);
        return commentMapper.insert(bc);
    }

    @Override
    public List<BoCommentVo> getBoComments(int boid, int pgNum, int pgSize) {
        PageHelper.startPage(pgNum, pgSize);
        List<BoCommentVo> retRes = customMapper.getBoComments(boid);
        for (BoCommentVo vo:retRes) {
            vo.setTimeDes(TimeDifferenceTool.showDateString(vo.getCreatedTime()));
            List<BoCommentVo> reps = customMapper.getBoChildComments(vo.getCommentId());
            for (BoCommentVo ro:reps) {
                ro.setTimeDes(TimeDifferenceTool.showDateString(ro.getCreatedTime()));
            }
            vo.setReplays(reps);
        }
        return retRes;
    }

    @Override
    public List<SiteStausVo> getActiveUserStatus() {
        return customMapper.getActiveUser(30);
    }

    @Override
    public List<SiteStausVo> getActiveBoBoStatus() {
        return customMapper.getActiveBoBo(30);
    }

    @Override
    public List<SiteStausVo> getNewUsers() {
        return customMapper.getNewUsers(30);
    }

    @Override
    public List<SiteStausVo> getNewComments() {
        return customMapper.getNewComments(30);
    }

    @Override
    public OperStatusVO getRelation(int boid, int uid) {
        OperStatusVO status = new OperStatusVO();
        if (uid == 0) {
            status.setFollowed(false);
            status.setLiked(false);
            status.setVoted(false);
            return status;
        }
        CoreUserFollowerKey followKey = new CoreUserFollowerKey();
        followKey.setUid(boid);
        followKey.setFollowerUid(uid);
        if (followerMapper.selectByPrimaryKey(followKey) == null) {
            status.setFollowed(false);
        } else {
            status.setFollowed(true);
        }
        BoFavLogKey favKey = new BoFavLogKey();
        favKey.setBoId(boid);
        favKey.setFromUid(uid);
        if (boFavLogMapper.selectByPrimaryKey(favKey) == null) {
            status.setLiked(false);
        } else {
            status.setLiked(true);
        }
        return status;
    }
}
